package com.loongtech.bi.manager.system;

import com.loongtech.bi.action.newsystem.SystemConfig;
import com.loongtech.bi.dao.CommonDao;
import com.loongtech.bi.entity.POJO.Page;
import com.loongtech.bi.entity.system.EntityMonitorConfig;
import com.loongtech.bi.entity.system.EntitySysProject;
import com.loongtech.bi.support.Log;
import com.loongtech.core.jpa.manager.ManagerBase;
import com.loongtech.core.util.ScheduleUtils;
import com.loongtech.core.util.Time;
import com.loongtech.core.util.Utils;
import org.apache.commons.collections.CollectionUtils;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.Trigger.TriggerState;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

import static com.loongtech.bi.manager.system.SysProjectManager.projectIdNameMap;

@Service
public class BiMonitorConfigManager extends ManagerBase<EntityMonitorConfig> {

    @Resource
    private Scheduler scheduler;
    @Resource
    private
    ConfigManager configManager;
    @Resource
    private SystemConfig systemConfig;
    @Resource(name = "commonDao")
    private CommonDao commonDao;

    private static final long serialVersionUID = 1L;

    /**
     * 系统启动时执行 添加同步服务器列表的任务和报表任务
     */
    public void addSyncServerMonitorConfig() {
        ScheduleUtils.createSyncServerScheduleJob(scheduler, configManager.getConfigValueByName(ConfigManager.PROJECT_URL), Time.currentDate(), new Date(Time.currentTime() + 100 * Time.DAY), 1, Integer.MAX_VALUE);
    }

    /**
     * 系统启动时执行 添加所有执行状态的任务
     */
    public void addAllEntityMonitorConfig() {
        List<EntityMonitorConfig> list = findByQuery("from EntityMonitorConfig  where status = ? or status = ? or status = ?", TriggerState.BLOCKED.name(), TriggerState.NORMAL.name(), TriggerState.ERROR.name());
        if (null != list && list.size() > 0) {
            for (EntityMonitorConfig e : list) {
                ScheduleUtils.createScheduleJob(scheduler, e);
            }
        }
    }


    /**
     * 增加任务
     */
    public void addEntityMonitorConfig(Long startTime, Long endTime, EntityMonitorConfig entity) throws Exception {
        if (entity.getCountNum() == null) {
            entity.setCountNum(Integer.MAX_VALUE);
        }
        if ("mid".equals(systemConfig.getServerType())) {
            Map<String, Object> params = new HashMap<>();
            EntitySysProject project = getByQuery("from EntitySysProject where id = ?", Integer.parseInt(entity.getGameId()));
            params.put("id", entity.getId());
            params.put("inquerySQL", entity.getInquerySQL());
            params.put("description", entity.getDescription());
            params.put("subDescription", entity.getSubDescription());
            params.put("groupId", entity.getGroupId());
            params.put("threshHold", entity.getThreshHold());
            params.put("status", TriggerState.NORMAL.toString());
            params.put("creatTime", Time.currentTime());
            params.put("starttime",startTime);
            params.put("endtime",endTime);
            params.put("intervalTime", entity.getIntervalTime());
            params.put("countNum", entity.getCountNum());
            params.put("gameId", entity.getGameId());
            String url = project.getProjectUrl() + "/monitorconfig/addStart.do";
            System.out.println("监控-开始任务请求地址为:" + url);
            String res = Utils.httpPost(url, params);
            if (res.contains("操作成功")) {
                entity.setStartTime(new Date(startTime));
                entity.setEndTime(new Date(endTime));
                entity.setStatus(TriggerState.NORMAL.name());
                persist(entity);
            } else {
                throw new Exception("请求返回失败:" + res);
            }
        } else {
            entity.setStartTime(new Date(startTime));
            entity.setEndTime(new Date(endTime));
            persist(entity);
            ScheduleUtils.createScheduleJob(scheduler, entity);
        }
    }

    /**
     * 开始全部任务
     */
    public void startAllEntityMonitorConfig(String... gameId) throws Exception {
        if ("mid".equals(systemConfig.getServerType())) {
            Map<String, Object> params = new HashMap<>();
            params.put("gameId", gameId[0]);
            EntitySysProject project = getByQuery("from EntitySysProject where id = ?", Integer.parseInt(gameId[0]));
            String url = project.getProjectUrl() + "/monitorconfig/startAll.do";
            Utils.httpPost(url, params);
//            if (res.contains("操作成功")) {
                excuteUpdateByHql("update EntityMonitorConfig set status = ? where status != ? and gameId = ?", TriggerState.NORMAL.name(), TriggerState.NORMAL.name(), gameId[0]);
//            } else {
//                throw new Exception("请求返回失败:" + res);
//            }
        } else {
//            List<EntityMonitorConfig> list = findByQuery("from EntityMonitorConfig where status != ? and gameId = ? ", TriggerState.NORMAL.name(), gameId[0]);
            List<EntityMonitorConfig> list = findByQuery("from EntityMonitorConfig where status != ? ", TriggerState.NORMAL.name());
            if (null != list && list.size() > 0) {
                for (EntityMonitorConfig s : list) {
                    ScheduleUtils.createScheduleJob(scheduler, s);
                }
            }
        }
    }

    /**
     * 废除任务
     */
    public void delEntityMonitorConfig(String id) throws Exception {
        if ("mid".equals(systemConfig.getServerType())) {
            Map<String, Object> params = new HashMap<>();
            EntityMonitorConfig entity = get(Integer.parseInt(id));
            EntitySysProject project = getByQuery("from EntitySysProject where id = ?", Integer.parseInt(entity.getGameId()));
            params.put("id", entity.getId());
            String url = project.getProjectUrl() + "/monitorconfig/abandonJob.do";
            Utils.httpPost(url, params);
//            if (res.contains("操作成功")) {
                entity.setStatus(TriggerState.COMPLETE.name());
                persist(entity);
//            } else {
//                throw new Exception("请求返回失败:" + res);
//            }
        } else {
            ScheduleUtils.deleteScheduleJob(scheduler, id);
        }
    }

    /**
     * 暂停全部任务
     */
    public void pauseAllEntityMonitorConfig(String... gameId) throws Exception {
        if ("mid".equals(systemConfig.getServerType())) {
            Map<String, Object> params = new HashMap<>();
            params.put("gameId", gameId[0]);
            EntitySysProject project = getByQuery("from EntitySysProject where id = ?", Integer.parseInt(gameId[0]));
            String url = project.getProjectUrl() + "/monitorconfig/pauseAll.do";
            Utils.httpPost(url, params);
//            if (res.contains("操作成功")) {
                excuteUpdateByHql("update EntityMonitorConfig set status = ? where status = ? or status = ? and gameId = ?", TriggerState.PAUSED.name(), TriggerState.NORMAL.name(), TriggerState.BLOCKED.name(), gameId[0]);
//            } else {
//                throw new Exception("请求返回失败:" + res);
//            }
        } else {
//            List<Integer> list = findByQuery("select id from EntityMonitorConfig where status = ? or status = ? and gameId = ?", TriggerState.NORMAL.name(), TriggerState.BLOCKED.name(), gameId[0]);
            List<Integer> list = findByQuery("select id from EntityMonitorConfig where status = ? or status = ? ", TriggerState.NORMAL.name(), TriggerState.BLOCKED.name());
            if (null != list && list.size() > 0) {
                for (Integer s : list) {
                    pauseMonitor(s.toString());
                }
            }
        }
    }

    /**
     * 恢复全部任务
     */
    public void resumeAllEntityMonitorConfig(String... gameId) throws Exception {
        if ("mid".equals(systemConfig.getServerType())) {
            Map<String, Object> params = new HashMap<>();
            params.put("gameId", gameId[0]);
            EntitySysProject project = getByQuery("from EntitySysProject where id = ?", Integer.parseInt(gameId[0]));
            String url = project.getProjectUrl() + "/monitorconfig/resumeAll.do";
            Utils.httpPost(url, params);
//            if (res.contains("操作成功")) {
                excuteUpdateByHql("update EntityMonitorConfig set status = ? where status = ? and gameId = ?", TriggerState.NORMAL.name(), TriggerState.PAUSED.name(), gameId[0]);
//            } else {
//                throw new Exception("请求返回失败:" + res);
//            }
        } else {
//            List<EntityMonitorConfig> list = findByQuery("from EntityMonitorConfig where status = ? and gameId = ?", TriggerState.PAUSED.name(), gameId[0]);
            List<EntityMonitorConfig> list = findByQuery("from EntityMonitorConfig where status = ? ", TriggerState.PAUSED.name());
            if (null != list && list.size() > 0) {
                for (EntityMonitorConfig s : list) {
                    resumeMonitor(s.getStartTime().getTime(), s.getEndTime().getTime(), s);
                }
            }
        }
    }

    /**
     * 修改任务
     */
    public void modifyEntityMonitorConfig(Long startTime, Long endTime, EntityMonitorConfig entity) throws Exception {
        if (entity.getCountNum() == null) {
            entity.setCountNum(Integer.MAX_VALUE);
        }
        if ("mid".equals(systemConfig.getServerType())) {
            Map<String, Object> params = new HashMap<>();
            EntitySysProject project = getByQuery("from EntitySysProject where id = ?", Integer.parseInt(entity.getGameId()));
            params.put("id", entity.getId());
            params.put("inquerySQL", entity.getInquerySQL());
            params.put("description", entity.getDescription());
            params.put("subDescription", entity.getSubDescription());
            params.put("groupId", entity.getGroupId());
            params.put("threshHold", entity.getThreshHold());
            params.put("status", TriggerState.NORMAL.toString());
            params.put("creatTime", Time.currentTime());
            params.put("starttime",startTime);
            params.put("endtime",endTime);
            params.put("intervalTime", entity.getIntervalTime());
            params.put("countNum", entity.getCountNum());
            params.put("gameId", entity.getGameId());

            String url = project.getProjectUrl() + "/monitorconfig/modify.do";
            System.out.println("监控-开始任务请求地址为:" + url);
            String res = Utils.httpPost(url, params);
            if (res.contains("操作成功")) {
                entity.setStartTime(new Date(startTime));
                entity.setEndTime(new Date(endTime));
                entity.setStatus(TriggerState.NORMAL.name());
                merge(entity);
            } else {
                throw new Exception("请求返回失败:" + res);
            }
        } else {
            entity.setStartTime(new Date(startTime));
            entity.setEndTime(new Date(endTime));
            merge(entity);
            ScheduleUtils.deleteScheduleJob(scheduler, entity.getId().toString());
            ScheduleUtils.createScheduleJob(scheduler, entity);
        }
    }

    /**
     * 恢复任务
     */
    public void resumeMonitor(Long startTime, Long endTime,EntityMonitorConfig entity) throws Exception {
        if ("mid".equals(systemConfig.getServerType())) {
            Map<String, Object> params = new HashMap<>();
            EntitySysProject project = getByQuery("from EntitySysProject where id = ?", Integer.parseInt(entity.getGameId()));
            params.put("id", entity.getId());
            params.put("inquerySQL", entity.getInquerySQL());
            params.put("description", entity.getDescription());
            params.put("subDescription", entity.getSubDescription());
            params.put("groupId", entity.getGroupId());
            params.put("threshHold", entity.getThreshHold());
            params.put("status", TriggerState.NORMAL.toString());
            params.put("creatTime", Time.currentTime());
            params.put("startTime",startTime);
            params.put("endTime",endTime);
            params.put("intervalTime", entity.getIntervalTime());
            params.put("countNum", entity.getCountNum());
            params.put("gameId", entity.getGameId());
            String url = project.getProjectUrl() + "/monitorconfig/resumeJob.do";
            Utils.httpPost(url, params);
//            if (res.contains("操作成功")) {
            entity.setStartTime(new Date(startTime));
            entity.setEndTime(new Date(endTime));
                entity.setStatus(TriggerState.NORMAL.name());
                merge(entity);
//            } else {
//                throw new Exception("请求返回失败:" + res);
//            }
        } else {
            entity.setStartTime(new Date(startTime));
            entity.setEndTime(new Date(endTime));
            ScheduleUtils.resumeJob(scheduler, entity);
        }
    }

    /**
     * 暂停任务
     */
    public void pauseMonitor(String id) throws Exception {
        if ("mid".equals(systemConfig.getServerType())) {
            Map<String, Object> params = new HashMap<>();
            EntityMonitorConfig entity = get(Integer.parseInt(id));
            EntitySysProject project = getByQuery("from EntitySysProject where id = ?", Integer.parseInt(entity.getGameId()));
            params.put("id", entity.getId());
            String url = project.getProjectUrl() + "/monitorconfig/pauseJob.do";
            Utils.httpPost(url, params);
//            if (res.contains("操作成功")) {
                entity.setStatus(TriggerState.PAUSED.name());
                persist(entity);
//            } else {
//                throw new Exception("请求返回失败:" + res);
//            }
        } else {
            ScheduleUtils.pauseJob(scheduler, id);
        }
    }

    /**
     * 获取所有任务的列表
     */
    public List<EntityMonitorConfig> queryList() {
        List<EntityMonitorConfig> list = findByQuery("from EntityMonitorConfig order by id");
        try {
            if (null != list && list.size() > 0) {
                for (EntityMonitorConfig vo : list) {

                    JobKey jobKey = ScheduleUtils.getJobKey(vo.getId().toString());
                    List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                    if (CollectionUtils.isEmpty(triggers)) {
                        vo.setStatus("NONE");
                        merge(vo);
                        continue;
                    }

                    // 这里一个任务可以有多个触发器， 但是我们一个任务对应一个触发器，所以只取第一个即可，清晰明了
                    Trigger trigger = triggers.iterator().next();
                    vo.setJobTrigger(trigger.getKey().getName());

                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    vo.setStatus(triggerState.name());
                    merge(vo);
                    // if (trigger instanceof CronTrigger) {
                    // CronTrigger cronTrigger = (CronTrigger) trigger;
                    // String cronExpression = cronTrigger.getCronExpression();
                    // vo.setCronExpression(cronExpression);
                    // }
                }
            }
        } catch (SchedulerException ex) {
            Log.bi.error("获取运行任务失败", ex);
            ex.printStackTrace();
        }
        return list;
    }

    // /**
    // * 查询运行中任务
    // */
    // public List<EntityMonitorConfig> queryExecutingJobList() {
    // List<EntityMonitorConfig> jobList = null;
    // try {
    // List<JobExecutionContext> executingJobs =
    // scheduler.getCurrentlyExecutingJobs();
    // jobList = new ArrayList<EntityMonitorConfig>(executingJobs.size());
    // for (JobExecutionContext executingJob : executingJobs) {
    // EntityMonitorConfig job = new EntityMonitorConfig();
    // JobDetail jobDetail = executingJob.getJobDetail();
    // JobKey jobKey = jobDetail.getKey();
    // Trigger trigger = executingJob.getTrigger();
    // job.setId(Integer.parseInt(jobKey.getName()));
    // job.setJobTrigger(trigger.getKey().getName());
    // Trigger.TriggerState triggerState =
    // scheduler.getTriggerState(trigger.getKey());
    // job.setStatus(triggerState.name());
    // if (trigger instanceof CronTrigger) {
    // CronTrigger cronTrigger = (CronTrigger) trigger;
    // String cronExpression = cronTrigger.getCronExpression();
    // job.setCronExpression(cronExpression);
    // }
    // jobList.add(job);
    // }
    // } catch (SchedulerException e) {
    // log.error("获取运行任务失败", e);
    // e.printStackTrace();
    // }
    // return jobList;
    // }

    /**
     * 查询任务
     */
    public List<EntityMonitorConfig> searchByCriteria(EntityMonitorConfig e) {
        List<Object> param = new ArrayList<>();
        StringBuilder hql = new StringBuilder(" from EntityMonitorConfig e where 1=1 ");
        if (e.getCountNum() != null && e.getCountNum() > 0) {
            hql.append(" and e.countNum = ?");
            param.add(e.getCountNum());
        }
        if (!Utils.isEmptyStr(e.getGameName())) {
            hql.append(" and e.gameName like ?");
            param.add("%" + e.getGameName() + "%");
        }
        if (e.getGameId() != null) {
            hql.append(" and e.gameId = ?");
            param.add(e.getGameId());
        }
        if (e.getId() != null) {
            hql.append(" and e.gameId = ?");
            param.add(e.getGameId());
        }
        if (e.getIntervalTime() != null && e.getIntervalTime() > 0) {
            hql.append(" and e.intervalTime = ?");
            param.add(e.getIntervalTime());
        }
        if (!Utils.isEmptyStr(e.getDescription())) {
            hql.append(" and e.description like ?");
            param.add("%" + e.getDescription() + "%");
        }
        if (!Utils.isEmptyStr(e.getSubDescription())) {
            hql.append(" and e.subDescription like ?");
            param.add("%" + e.getSubDescription() + "%");
        }
        if (!Utils.isEmptyStr(e.getInquerySQL())) {
            hql.append(" and e.inquerySQL like ?");
            param.add("%" + e.getInquerySQL() + "%");
        }
        if (null != e.getThreshHold()) {
            hql.append(" and e.threshHold = ?");
            param.add(e.getThreshHold());
        }
        if (null != e.getGroupId()) {
            hql.append(" and e.groupId = ?");
            param.add(e.getThreshHold());
        }
        if (e.getStartTime() != null) {
            // hql.append(" and e.startTime >= '" +
            // Time.getDateAndHourStr(e.getStartTime()) + "'");
            hql.append(" and e.startTime >= ?");
            param.add(e.getStartTime());
        }
        if (e.getEndTime() != null) {
            // hql.append(" and e.endTime <= '" +
            // Time.getDateAndHourStr(e.getEndTime()) + "'");
            hql.append(" and e.endTime <= ?");
            param.add(e.getEndTime());
        }
        hql.append(" order by e.id");
        List<EntityMonitorConfig> list = findByQuery(hql.toString(), param.toArray());
        try {
            if (null != list && list.size() > 0) {
                for (EntityMonitorConfig vo : list) {

                    JobKey jobKey = ScheduleUtils.getJobKey(vo.getId().toString());
                    List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                    if (CollectionUtils.isEmpty(triggers)) {
                        vo.setStatus("NONE");
                        merge(vo);
                        continue;
                    }
                    // 这里一个任务可以有多个触发器， 但是我们一个任务对应一个触发器，所以只取第一个即可，清晰明了
                    Trigger trigger = triggers.iterator().next();
                    vo.setJobTrigger(trigger.getKey().getName());

                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    vo.setStatus(triggerState.name());
                    merge(vo);
                }
            }
        } catch (SchedulerException ex) {
            Log.bi.error("获取运行任务失败", ex);
            ex.printStackTrace();
        }
        return list;
    }

    //springmvc 查询
    public Page<List<EntityMonitorConfig>> queryByCriteria(Integer curPage, Integer pageSize, EntityMonitorConfig e) {
        List<Object> param = new ArrayList<>();
        StringBuilder hql = new StringBuilder(" from EntityMonitorConfig e where 1=1 ");
        if (e.getCountNum() != null && e.getCountNum() > 0) {
            hql.append(" and e.countNum = ?");
            param.add(e.getCountNum());
        }
        if (e.getId() != null) {
            hql.append(" and e.id = ?");
            param.add(e.getId());
        }
        if (e.getGameId() != null) {
            hql.append(" and e.gameId = ?");
            param.add(e.getGameId());
        }
        if (e.getIntervalTime() != null && e.getIntervalTime() > 0) {
            hql.append(" and e.intervalTime = ?");
            param.add(e.getIntervalTime());
        }
        if (!Utils.isEmptyStr(e.getDescription())) {
            hql.append(" and e.description like ?");
            param.add("%" + e.getDescription() + "%");
        }
        if (!Utils.isEmptyStr(e.getSubDescription())) {
            hql.append(" and e.subDescription like ?");
            param.add("%" + e.getSubDescription() + "%");
        }
        if (!Utils.isEmptyStr(e.getInquerySQL())) {
            hql.append(" and e.inquerySQL like ?");
            param.add("%" + e.getInquerySQL() + "%");
        }
        if (null != e.getThreshHold()) {
            hql.append(" and e.threshHold = ?");
            param.add(e.getThreshHold());
        }
        if (null != e.getGroupId()) {
            hql.append(" and e.groupId = ?");
            param.add(e.getGroupId());
        }
        if (e.getStartTime() != null) {
            // hql.append(" and e.startTime >= '" +
            // Time.getDateAndHourStr(e.getStartTime()) + "'");
            hql.append(" and e.startTime >= ?");
            param.add(e.getStartTime());
        }
        if (e.getEndTime() != null) {
            // hql.append(" and e.endTime <= '" +
            // Time.getDateAndHourStr(e.getEndTime()) + "'");
            hql.append(" and e.endTime <= ?");
            param.add(e.getEndTime());
        }
        hql.append(" order by e.id asc");
        //总数
        Integer totalSize = countNum(hql.toString(), param.toArray());
        //数据
        List<EntityMonitorConfig> list = findByQuery((curPage - 1) * pageSize, pageSize, hql.toString(), param.toArray());
        try {
            if (null != list && list.size() > 0) {
                for (EntityMonitorConfig vo : list) {
                    //取项目名字
                    String gameid = vo.getGameId();
                    for (Map.Entry<String, String> entry : projectIdNameMap.entrySet()) {
                        gameid = gameid.replace(entry.getKey() + ",", entry.getValue() + ",");
                    }
                    vo.setGameName(gameid);
//                    //更新任务状态
//                    JobKey jobKey = ScheduleUtils.getJobKey(vo.getId().toString());
//                    List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
//                    if (CollectionUtils.isEmpty(triggers)) {
//                        vo.setStatus("NONE");
//                        merge(vo);
//                        continue;
//                    }
//                    // 这里一个任务可以有多个触发器， 但是我们一个任务对应一个触发器，所以只取第一个即可，清晰明了
//                    Trigger trigger = triggers.iterator().next();
//                    vo.setJobTrigger(trigger.getKey().getName());
//
//                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
//                    vo.setStatus(triggerState.name());
//                    merge(vo);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return new Page<>(list, totalSize, curPage, pageSize);
    }
}
